package org.ytor.core.sysapi.monitor.logic;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.ytor.common.exception.BaseException;
import org.ytor.common.util.Dates;
import org.ytor.common.util.Numbers;
import org.ytor.common.util.Strs;
import org.ytor.core.sysapi.monitor.resp.*;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.OperatingSystem;

import javax.sql.DataSource;
import java.lang.management.*;
import java.lang.reflect.Method;
import java.util.*;

/**
 * created by yangtong on 2025/7/6 20:59:42
 * <br/>
 * 系统监控服务实现
 */
@Service
@Slf4j
public class SystemMonitorLogic {

    @Autowired(required = false)
    private DataSource dataSource;

    private final OperatingSystem os;
    private final CentralProcessor processor;
    private final GlobalMemory globalMemory;

    // 操作系统相关缓存（不会轻易变化的数据，计算一次即可）
    private final Long totalPhysicalMemory;
    private final Integer cpuPhysicalCores;
    private final Integer cpuLogicalCores;
    private final String cpuName;
    private final String cpuArch;
    private final String versionInfo;
    private final String hostName;

    // CPU计算相关缓存（避免频繁计算）
    private volatile long[] lastTicks;
    private volatile long lastTickTime = 0;
    private volatile double lastCpuUsage = 0.0;
    private static final long CPU_CACHE_TIME = 2000; // 2秒内复用CPU计算结果

    public SystemMonitorLogic() {
        SystemInfo systemInfo = new SystemInfo();
        this.os = systemInfo.getOperatingSystem();
        HardwareAbstractionLayer hal = systemInfo.getHardware();
        this.processor = hal.getProcessor();
        this.lastTicks = processor.getSystemCpuLoadTicks();
        this.globalMemory = hal.getMemory();

        // 缓存相关数据
        //物理内存
        this.totalPhysicalMemory = globalMemory.getTotal();

        //CPU核心数量
        this.cpuPhysicalCores = processor.getPhysicalProcessorCount();
        this.cpuLogicalCores = processor.getLogicalProcessorCount();

        //CPU名称
        String cpuName = processor.getProcessorIdentifier().getName();
        if (cpuName != null) {
            cpuName = cpuName.trim().replaceAll("\\s+", " ");
        }
        this.cpuName = cpuName;

        // CPU架构
        String cpuArch = processor.getProcessorIdentifier().getMicroarchitecture();
        if (cpuArch == null || cpuArch.trim().isEmpty()) {
            cpuArch = "Unknown";
        }
        this.cpuArch = cpuArch;

        // 系统版本
        this.versionInfo = os.getVersionInfo().toString();
        // 设备名称
        this.hostName = os.getNetworkParams().getHostName();
    }

    public OperateSystemBasicResp operateSystemBasic() {
        try {
            // CPU主频
            long maxFreq = processor.getMaxFreq();
            String cpuFreq = maxFreq > 0 ?
                    String.format("%.2f GHz", maxFreq / 1_000_000_000.0) :
                    "Unknown";

            return new OperateSystemBasicResp()
                    .setHostName(hostName)
                    .setOsName(os.getFamily())
                    .setOsManufacturer(os.getManufacturer())
                    .setOsVersion(versionInfo)
                    .setOsArch(System.getProperty("os.arch"))
                    .setCpuPhysicalCores(cpuPhysicalCores)
                    .setCpuLogicalCores(cpuLogicalCores)
                    .setCpuName(cpuName)
                    .setCpuMaxFreqGHz(cpuFreq)
                    .setCpuArch(cpuArch)
                    .setTotalPhysicalMemory(Strs.formatSize(totalPhysicalMemory));

        } catch (Exception e) {
            log.error("获取操作系统信息失败", e);
            throw new BaseException("获取操作系统信息失败: " + e.getMessage());
        }
    }


    public OperateSystemRealtimeResp operateSystemRealtime() {
        long timestamp = System.currentTimeMillis();
        // 已使用物理内存
        long usedPhysicalMemory = getUsedPhysicalMemory();

        return new OperateSystemRealtimeResp()
                .setCpuUsageRate(getCpuUsage())
                .setUsedPhysicalMemory(usedPhysicalMemory)
                .setPhysicalMemoryUsageRate(Numbers.div(usedPhysicalMemory, totalPhysicalMemory, 3))
                .setTimestamp(timestamp)
                ;
    }


    public JvmBasicResp jvmBasic() {
        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
        MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();

        //进程ID
        String runtimeName = runtimeMXBean.getName(); // 格式：pid@hostname

        // 堆内存
        MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
        // 最大堆内存（-Xmx参数设置的值）
        long maxHeapBytes = heapMemoryUsage.getMax();

        // 初始堆内存（-Xms参数设置的值）
        long initHeapBytes = heapMemoryUsage.getInit();

        // 获取非堆内存使用情况
        MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
        // 最大非堆内存（可能是-1）
        long maxNonHeapBytes = nonHeapMemoryUsage.getMax();

        return new JvmBasicResp()
                .setVersion(System.getProperty("java.version"))
                .setVendor(System.getProperty("java.vendor"))
                .setJvmName(runtimeMXBean.getVmName())
                .setStartTime(Dates.formatDateTime(new Date(runtimeMXBean.getStartTime())))
                .setPid(runtimeName.split("@")[0])
                .setWorkingDirectory(System.getProperty("user.dir"))
                .setUsername(System.getProperty("user.name"))
                .setMaxHeapMemory(Strs.formatSize(maxHeapBytes))
                .setInitHeapMemory(Strs.formatSize(initHeapBytes))
                .setMaxNonHeapMemory(maxNonHeapBytes == -1 ? "无限制" : Strs.formatSize(maxNonHeapBytes))
                ;
    }


    public JvmRealtimeResp jvmRealtime() {
        long timestamp = System.currentTimeMillis();
        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
        MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();

        //JVM运行时长
        long uptime = runtimeMXBean.getUptime();

        MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
        // 已提交内存
        long committedHeap = heapMemoryUsage.getCommitted();
        // 当前已使用的堆内存
        long usedHeapBytes = heapMemoryUsage.getUsed();

        MemoryUsage nonHeapUsage = memoryMXBean.getNonHeapMemoryUsage();
        // 已提交非堆内存
        long committedNonHeap = nonHeapUsage.getCommitted();
        // 已使用非堆内存
        long usedNonHeap = nonHeapUsage.getUsed();

        // 线程数
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        int threadCount = threadMXBean.getThreadCount();

        // 数据库连接池信息
        int activeConnections = 0;
        double connectionUsage = 0.0;
        try {
            PoolStats s = getPoolStats(dataSource);
            activeConnections = s.active;
            connectionUsage = s.max > 0 ? (double) s.active / s.max * 100 : 0.0;
        } catch (Exception e) {
            log.debug("获取连接池实时指标失败：{}", e.getMessage());
        }


        return new JvmRealtimeResp()
                .setTimestamp(timestamp)
                .setCommittedHeapMemory(committedHeap)
                .setCommittedHeapMemoryStr(Strs.formatSize(committedHeap))
                .setUsedHeapMemory(usedHeapBytes)
                .setUsedHeapMemoryStr(Strs.formatSize(usedHeapBytes))
                .setFreeHeapMemory(committedHeap - usedHeapBytes)
                .setHeapMemoryUsageRate(Numbers.div(usedHeapBytes, committedHeap, 3))
                .setCommittedNonHeapMemory(committedNonHeap)
                .setCommittedNonHeapMemoryStr(Strs.formatSize(committedNonHeap))
                .setUsedNonHeapMemory(usedNonHeap)
                .setUsedNonHeapMemoryStr(Strs.formatSize(usedNonHeap))
                .setFreeNonHeapMemory(committedNonHeap - usedNonHeap)
                .setNonHeapMemoryUsageRate(Numbers.div(usedNonHeap, committedNonHeap, 3))
                .setThreadCount(threadCount)
                .setActiveConnections(activeConnections)
                .setConnectionUsage(connectionUsage)
                .setUptime(uptime)
                .setFormattedUptime(Strs.formatMillis(uptime))
                ;
    }

    /**
     * 获取JVM启动参数
     */

    public JvmArgumentsResp getJvmArguments() {
        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
        List<String> inputArguments = runtimeMXBean.getInputArguments();

        Map<String, String> memoryParams = new HashMap<>();
        Map<String, String> gcParams = new HashMap<>();
        Map<String, String> systemProps = new HashMap<>();

        // 分类JVM参数
        for (String arg : inputArguments) {
            if (arg.startsWith("-Xms") || arg.startsWith("-Xmx") || arg.startsWith("-XX:") &&
                    (arg.contains("Memory") || arg.contains("Heap") || arg.contains("Stack"))) {
                if (arg.contains("=")) {
                    String[] parts = arg.split("=", 2);
                    memoryParams.put(parts[0], parts[1]);
                } else {
                    memoryParams.put(arg, "true");
                }
            } else if (arg.startsWith("-XX:") &&
                    (arg.contains("GC") || arg.contains("G1") || arg.contains("Parallel") || arg.contains("CMS"))) {
                if (arg.contains("=")) {
                    String[] parts = arg.split("=", 2);
                    gcParams.put(parts[0], parts[1]);
                } else {
                    gcParams.put(arg, "true");
                }
            } else if (arg.startsWith("-D")) {
                if (arg.contains("=")) {
                    String[] parts = arg.split("=", 2);
                    systemProps.put(parts[0], parts[1]);
                }
            }
        }

        return JvmArgumentsResp.builder()
                .allArguments(inputArguments)
                .memoryParameters(memoryParams)
                .gcParameters(gcParams)
                .systemProperties(systemProps)
                .build();
    }

    /**
     * 获取堆内存区域信息（按区分组）
     */

    public Map<String, List<MemoryPoolDetailResp>> getHeapMemoryPools() {
        Map<String, List<MemoryPoolDetailResp>> result = new HashMap<>();

        List<MemoryPoolMXBean> memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans();

        for (MemoryPoolMXBean poolBean : memoryPoolMXBeans) {
            if (poolBean.getType() == MemoryType.HEAP) {
                MemoryUsage usage = poolBean.getUsage();

                MemoryPoolDetailResp poolInfo = MemoryPoolDetailResp.builder()
                        .name(poolBean.getName())
                        .type(poolBean.getType().name())
                        .used(usage.getUsed())
                        .committed(usage.getCommitted())
                        .max(usage.getMax())
                        .usageRate(usage.getMax() > 0 ? (double) usage.getUsed() / usage.getMax() * 100 : 0)
                        .build();

                // 根据名称分类
                String category = categorizeMemoryPool(poolBean.getName());
                result.computeIfAbsent(category, k -> new ArrayList<>()).add(poolInfo);
            }
        }

        return result;
    }

    /**
     * 获取所有内存池信息（包括非堆）
     */

    public List<MemoryPoolDetailResp> getAllMemoryPools() {
        List<MemoryPoolDetailResp> result = new ArrayList<>();
        List<MemoryPoolMXBean> memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans();

        for (MemoryPoolMXBean poolBean : memoryPoolMXBeans) {
            MemoryUsage usage = poolBean.getUsage();

            result.add(MemoryPoolDetailResp.builder()
                    .name(poolBean.getName())
                    .type(poolBean.getType().name() + " - " + categorizeDetailedPool(poolBean.getName()))
                    .used(usage.getUsed())
                    .committed(usage.getCommitted())
                    .max(usage.getMax())
                    .usageRate(usage.getMax() > 0 ? (double) usage.getUsed() / usage.getMax() * 100 : 0)
                    .build());
        }

        return result;
    }

    /**
     * 获取类加载详细信息
     */

    public ClassLoadingDetailResp getClassLoadingDetail() {
        ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();

        return ClassLoadingDetailResp.builder()
                .loadedClassCount(classLoadingMXBean.getLoadedClassCount())
                .totalLoadedClassCount(classLoadingMXBean.getTotalLoadedClassCount())
                .unloadedClassCount(classLoadingMXBean.getUnloadedClassCount())
                .build();
    }

    /**
     * 获取数据库连接池信息
     */

    public DatabaseInfoRealtimeResp databaseInfoRealtime() {
        if (dataSource == null) {
            return DatabaseInfoRealtimeResp.builder()
                    .dataSourceClass("未配置数据源")
                    .activeConnections(0).idleConnections(0).maxConnections(0).minConnections(0)
                    .build();
        }
        try {
            PoolStats s = getPoolStats(dataSource);
            return DatabaseInfoRealtimeResp.builder()
                    .dataSourceClass(s.provider)
                    .activeConnections(s.active)
                    .idleConnections(s.idle)
                    .maxConnections(s.max)
                    .minConnections(s.min)
                    .build();
        } catch (Exception e) {
            log.error("获取数据库连接池信息失败", e);
            return DatabaseInfoRealtimeResp.builder()
                    .dataSourceClass("获取失败: " + e.getMessage())
                    .activeConnections(0).idleConnections(0).maxConnections(0).minConnections(0)
                    .build();
        }
    }


    /**
     * 获取Druid数据源信息（使用反射）
     */
    private DatabaseInfoRealtimeResp getDruidDataSourceInfo() {
        try {
            Class<?> clazz = dataSource.getClass();
            Method getActiveCountMethod = clazz.getMethod("getActiveCount");
            Method getPoolingCountMethod = clazz.getMethod("getPoolingCount");
            Method getMaxActiveMethod = clazz.getMethod("getMaxActive");
            Method getMinIdleMethod = clazz.getMethod("getMinIdle");

            return DatabaseInfoRealtimeResp.builder()
                    .activeConnections((Integer) getActiveCountMethod.invoke(dataSource))
                    .idleConnections((Integer) getPoolingCountMethod.invoke(dataSource))
                    .maxConnections((Integer) getMaxActiveMethod.invoke(dataSource))
                    .minConnections((Integer) getMinIdleMethod.invoke(dataSource))
                    .dataSourceClass("DruidDataSource")
                    .build();
        } catch (Exception e) {
            log.error("获取Druid数据源信息失败", e);
            return DatabaseInfoRealtimeResp.builder()
                    .dataSourceClass("DruidDataSource (获取详情失败)")
                    .activeConnections(0)
                    .idleConnections(0)
                    .maxConnections(0)
                    .minConnections(0)
                    .build();
        }
    }

    /**
     * 获取GC信息
     */

    public GcInfoResp getGcInfo() {
        List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();

        long totalGcCount = 0;
        long totalGcTime = 0;
        List<GcDetailResp> gcDetailResps = new ArrayList<>();

        for (GarbageCollectorMXBean gcBean : gcBeans) {
            long collectionCount = gcBean.getCollectionCount();
            long collectionTime = gcBean.getCollectionTime();

            if (collectionCount >= 0) {
                totalGcCount += collectionCount;
            }
            if (collectionTime >= 0) {
                totalGcTime += collectionTime;
            }

            gcDetailResps.add(GcDetailResp.builder()
                    .name(gcBean.getName())
                    .collectionCount(Math.max(0, collectionCount))
                    .collectionTime(Math.max(0, collectionTime))
                    .build());
        }

        return GcInfoResp.builder()
                .totalGcCount(totalGcCount)
                .totalGcTime(totalGcTime)
                .gcDetailResps(gcDetailResps)
                .build();
    }

    /**
     * 获取线程信息
     */

    public ThreadInfoResp getThreadInfo() {
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();

        return ThreadInfoResp.builder()
                .totalThreads(threadMXBean.getThreadCount())
                .activeThreads(threadMXBean.getThreadCount())
                .daemonThreads(threadMXBean.getDaemonThreadCount())
                .peakThreads(threadMXBean.getPeakThreadCount())
                .build();
    }

    /**
     * 强制GC
     */

    public GcResultResp forceGc() {
        try {
            long beforeMemory = getUsedMemory();
            long beforeTime = System.currentTimeMillis();

            System.gc();

            // 等待一小段时间让GC完成
            Thread.sleep(100);

            long afterMemory = getUsedMemory();
            long afterTime = System.currentTimeMillis();

            long memoryReleased = beforeMemory - afterMemory;
            long duration = afterTime - beforeTime;

            log.info("强制GC完成 - 耗时: {}ms, 内存释放: {}MB", duration, memoryReleased / 1024 / 1024);

            return GcResultResp.builder()
                    .success(true)
                    .duration(duration)
                    .memoryBefore(beforeMemory)
                    .memoryAfter(afterMemory)
                    .memoryReleased(memoryReleased)
                    .memoryReleasedMB(memoryReleased / 1024 / 1024)
                    .build();

        } catch (Exception e) {
            log.error("强制GC失败", e);
            return GcResultResp.builder()
                    .success(false)
                    .duration(0L)
                    .memoryBefore(0L)
                    .memoryAfter(0L)
                    .memoryReleased(0L)
                    .memoryReleasedMB(0L)
                    .error(e.getMessage())
                    .build();
        }
    }


    /**
     * 获取磁盘信息
     */

    public DiskInfoResp getDiskInfo() {
        try {
            java.io.File[] roots = java.io.File.listRoots();
            List<DiskPartitionResp> partitions = new ArrayList<>();

            for (java.io.File root : roots) {
                long totalSpace = root.getTotalSpace();
                long usableSpace = root.getUsableSpace();
                long usedSpace = totalSpace - usableSpace;

                DiskPartitionResp partition = DiskPartitionResp.builder()
                        .name(root.getAbsolutePath())
                        .mountPoint(root.getAbsolutePath())
                        .totalSpace(totalSpace)
                        .usableSpace(usableSpace)
                        .usedSpace(usedSpace)
                        .usageRate(totalSpace > 0 ? (double) usedSpace / totalSpace * 100 : 0)
                        .totalSpaceGB(totalSpace / 1024.0 / 1024.0 / 1024.0)
                        .usableSpaceGB(usableSpace / 1024.0 / 1024.0 / 1024.0)
                        .usedSpaceGB(usedSpace / 1024.0 / 1024.0 / 1024.0)
                        .build();

                partitions.add(partition);
            }

            return DiskInfoResp.builder()
                    .partitions(partitions)
                    .build();

        } catch (Exception e) {
            log.error("获取磁盘信息失败", e);
            return DiskInfoResp.builder()
                    .partitions(new ArrayList<>())
                    .error(e.getMessage())
                    .build();
        }
    }

    /**
     * 获取操作系统实际使用的物理内存
     */
    private long getUsedPhysicalMemory() {
        try {
            // 获取当前可用内存
            long availableMemory = globalMemory.getAvailable();
            // 计算已使用内存 = 总内存 - 可用内存
            return totalPhysicalMemory - availableMemory;
        } catch (Exception e) {
            log.warn("获取操作系统物理内存使用量失败，使用备用方案", e);
            return getUsedPhysicalMemoryFallback();
        }
    }

    /**
     * 备用方案：使用JMX获取操作系统内存信息
     */
    private long getUsedPhysicalMemoryFallback() {
        try {
            OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
            if (osBean instanceof com.sun.management.OperatingSystemMXBean sunOsBean) {
                long totalPhysical = sunOsBean.getTotalMemorySize();
                long freePhysical = sunOsBean.getFreeMemorySize();
                return totalPhysical - freePhysical;
            }
        } catch (Exception e) {
            log.warn("JMX获取操作系统内存信息失败", e);
        }
        // 如果都失败了，返回0
        return 0L;
    }

    /**
     * 获取已使用内存
     */
    private long getUsedMemory() {
        MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
        return memoryMXBean.getHeapMemoryUsage().getUsed();
    }

    /**
     * 获取CPU使用率
     */
    private double getCpuUsage() {
        long currentTime = System.currentTimeMillis();

        // 如果距离上次计算不足2秒，直接返回缓存值
        if (currentTime - lastTickTime < CPU_CACHE_TIME) {
            return lastCpuUsage;
        }

        try {
            // 获取当前tick
            long[] currentTicks = processor.getSystemCpuLoadTicks();

            // 计算CPU使用率
            double cpuUsage = processor.getSystemCpuLoadBetweenTicks(lastTicks) * 100;

            // 更新缓存
            this.lastTicks = currentTicks;
            this.lastTickTime = currentTime;
            this.lastCpuUsage = Math.max(0, Math.min(100, cpuUsage));

            return lastCpuUsage;

        } catch (Exception e) {
            log.warn("OSHI获取CPU使用率失败，尝试JMX方式", e);
            return getJmxCpuUsage();
        }
    }

    /**
     * 使用JMX获取CPU使用率（备用方案）
     */
    private double getJmxCpuUsage() {
        try {
            OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
            if (osBean instanceof com.sun.management.OperatingSystemMXBean sunOsBean) {
                double cpuLoad = sunOsBean.getCpuLoad();
                if (cpuLoad >= 0) {
                    // 更新缓存
                    this.lastCpuUsage = cpuLoad * 100;
                    this.lastTickTime = System.currentTimeMillis();
                    return lastCpuUsage;
                }
            }
        } catch (Exception e) {
            log.warn("JMX获取CPU使用率失败", e);
        }
        return 0.0;
    }

    /**
     * 内存池分类
     */
    private String categorizeMemoryPool(String poolName) {
        String name = poolName.toLowerCase();
        if (name.contains("eden")) {
            return "新生代-Eden区";
        } else if (name.contains("survivor")) {
            return "新生代-Survivor区";
        } else if (name.contains("old") || name.contains("tenured")) {
            return "老年代";
        } else if (name.contains("young") || name.contains("new")) {
            return "新生代";
        } else {
            return "其他堆区域";
        }
    }

    /**
     * 详细内存池分类
     */
    private String categorizeDetailedPool(String poolName) {
        String name = poolName.toLowerCase();
        if (name.contains("metaspace")) return "元空间";
        if (name.contains("code cache")) return "代码缓存";
        if (name.contains("compressed class")) return "压缩类空间";
        if (name.contains("eden")) return "新生代Eden区";
        if (name.contains("survivor")) return "新生代Survivor区";
        if (name.contains("old") || name.contains("tenured")) return "老年代";
        return "其他";
    }

    /**
     * 解包被代理的数据源（优先拿到真实底层 DataSource）
     */
    private DataSource unwrapDataSource(DataSource ds) {
        if (ds == null) return null;
        try {
            // 标准 JDBC Wrapper 解包
            if (ds instanceof java.sql.Wrapper w && w.isWrapperFor(DataSource.class)) {
                DataSource un = w.unwrap(DataSource.class);
                if (un != null) return un;
            }
        } catch (Exception ignore) {
        }

        // 常见 Spring 代理（DelegatingDataSource / LazyConnectionDataSourceProxy）
        try {
            // 尝试读取 getTargetDataSource
            var m = ds.getClass().getMethod("getTargetDataSource");
            m.setAccessible(true);
            Object inner = m.invoke(ds);
            if (inner instanceof DataSource) return (DataSource) inner;
        } catch (Exception ignore) {
        }

        return ds;
    }

    /**
     * 反射获取 Hikari 指标
     */
    private PoolStats tryHikari(DataSource realDs) {
        try {
            if (!"com.zaxxer.hikari.HikariDataSource".equals(realDs.getClass().getName())) return null;

            Class<?> hds = Class.forName("com.zaxxer.hikari.HikariDataSource");
            Class<?> mx = Class.forName("com.zaxxer.hikari.HikariPoolMXBean");

            Object hikari = hds.cast(realDs);
            Object mxBean = hds.getMethod("getHikariPoolMXBean").invoke(hikari);
            if (mxBean == null) return new PoolStats("HikariCP", 0, 0,
                    (int) hds.getMethod("getMaximumPoolSize").invoke(hikari),
                    (int) hds.getMethod("getMinimumIdle").invoke(hikari));

            int active = (int) mx.getMethod("getActiveConnections").invoke(mxBean);
            int idle = (int) mx.getMethod("getIdleConnections").invoke(mxBean);
            int max = (int) hds.getMethod("getMaximumPoolSize").invoke(hikari);
            int min = (int) hds.getMethod("getMinimumIdle").invoke(hikari);

            return new PoolStats("HikariCP", active, idle, max, min);
        } catch (Throwable e) {
            log.debug("反射读取 Hikari 指标失败：{}", e.getMessage());
            return null;
        }
    }

    /**
     * 反射获取 Druid 指标（兼容 Spring Boot 3 的 druid starter）
     */
    private PoolStats tryDruid(DataSource realDs) {
        try {
            String name = realDs.getClass().getName();
            if (!name.contains("DruidDataSource")) return null;

            Class<?> c = realDs.getClass();
            int active = (int) c.getMethod("getActiveCount").invoke(realDs);
            int idle = (int) c.getMethod("getPoolingCount").invoke(realDs);
            int max = (int) c.getMethod("getMaxActive").invoke(realDs);
            int min = (int) c.getMethod("getMinIdle").invoke(realDs);
            return new PoolStats("DruidDataSource", active, idle, max, min);
        } catch (Throwable e) {
            log.debug("反射读取 Druid 指标失败：{}", e.getMessage());
            return null;
        }
    }

    // 统一入口：优先 Hikari，再尝试 Druid；都不是则 Unknown
    private PoolStats getPoolStats(DataSource ds) {
        if (ds == null) return new PoolStats("Unknown", 0, 0, 0, 0);
        DataSource real = unwrapDataSource(ds);

        PoolStats h = tryHikari(real);
        if (h != null) return h;

        PoolStats d = tryDruid(real);
        if (d != null) return d;

        return new PoolStats(real.getClass().getSimpleName(), 0, 0, 0, 0);
    }

    /**
     * 数据库连接池信息
     */
    private static final class PoolStats {
        /**
         * "HikariCP" / "DruidDataSource" / "Unknown"
         */
        final String provider;
        final int active;
        final int idle;
        final int max;
        final int min;

        PoolStats(String provider, int active, int idle, int max, int min) {
            this.provider = provider;
            this.active = active;
            this.idle = idle;
            this.max = max;
            this.min = min;
        }
    }

}